

#include "SD_FileMan_SecPtr.h"

FILEMAN_SP_STRUCT FM_SP[DATATYPE_CNT];
FILEMAN_SP_STRUCT FM_SP_POS;

__ALIGN_BEGIN POS_INFO pos_Info; __ALIGN_END

__ALIGN_BEGIN uint8_t FM_SP_Buf[512];__ALIGN_END


extern HAL_SD_ErrorTypedef	ReadSdSec(uint8_t *readbuff, uint32_t sec, uint16_t BlockSize, uint32_t NumberOfBlocks);
extern HAL_SD_ErrorTypedef	WriteSdSec(uint8_t *writebuff, uint32_t sec, uint16_t BlockSize, uint32_t NumberOfBlocks);
//
uint8_t SUM_ECC(uint8_t *buf,uint32_t len)
{
	uint8_t sum = 0;
	uint32_t i;
	for(i=0;i<len;i++)
	{
		sum += buf[i];
	}
	sum = ~sum;
	sum++;
	return sum;
}
//
uint32_t FM_SP_SecAdd(uint32_t index,uint32_t offset,uint32_t start,uint32_t total)
{
	index += offset;
	while(index>=(start+total))
	{
		index -= total;
	}
	return (index);
}
//
uint8_t FM_SP_SecOutOfRang(uint32_t index,uint32_t start,uint32_t total)
{
	if(index<start||index>=(start+total))
		return 1;
	return 0;
}
/*
 * before calling this function, the "pos->PosData" should have been set.
 * only 0 or 1 is admitted for "offset".
 * set "pos->posIndex" / "pos->PosSec" / and the SUM_ECC of "pos" structure.
 */
void FM_SP_NewPos(POS_INFO *pos,uint32_t offset)
{
	uint8_t *buf;
	//renew index
	pos->posIndex += offset;
	//Save new pos_info
	pos->PosSec = FM_SP_SecAdd(pos->PosSec,offset,FM_SP_POS.STARTSEC,FM_SP_POS.TOTALSEC);
	
	buf = (uint8_t*)pos;
	
	buf[511] = SUM_ECC(buf,511);
	return;
}
//
uint8_t FM_SP_PosIsNext(POS_INFO *pos,POS_INFO *nextpos)
{
	if((pos->posIndex+1) == nextpos->posIndex)
		return 1;
	return 0;
}
//
void FM_SP_SetPos(uint8_t* s,uint8_t  *t)
{
	uint16_t i;
	POS_INFO *pos;
	if(s==0)
	{
		for(i=0;i<512;i++)
		{
			t[i] = 0;
		}
		pos = (POS_INFO*)t;
		
		pos->ID = POSINFOID;
		pos->PosSec = FM_SP_POS.STARTSEC;
		pos->posIndex = 0;
		
		for(i=0;i<DATATYPE_CNT;i++)
		{
			pos->PosData.CopyInfoValid[i] = 1;
			pos->PosData.NextSecToSave[i] = FM_SP[i].STARTSEC;
			pos->PosData.SecOfCopyStart[i] = FM_SP[i].STARTSEC;
			pos->PosData.TotSavedSecCnt[i] = 0;
		}
		
		FM_SP_NewPos(pos,0);
	}
	else
	{
		for(i=0;i<512;i++)
		{
			t[i] = s[i];
		}
	}
	
}
//
uint8_t FM_SP_PosCheckErr(POS_INFO *pos,uint32_t sec)
{
	uint8_t *buf,ecc,i;
	
	if(pos->ID != POSINFOID)
	{
		return 1;
	}
	
	if(pos->PosSec != sec && sec != 0xFFFFFFFF)
		return 2;
	
	buf = (uint8_t*)pos;
	ecc = SUM_ECC(buf,511);
	if(ecc!=buf[511])
		return 3;
	
	for(i=0;i<DATATYPE_CNT;i++)
	{
		if(FM_SP_SecOutOfRang(pos->PosData.NextSecToSave[i],FM_SP[i].STARTSEC,FM_SP[i].TOTALSEC))
			return 4;
		if(FM_SP_SecOutOfRang(pos->PosData.SecOfCopyStart[i],FM_SP[i].STARTSEC,FM_SP[i].TOTALSEC))
			return 5;
	}
	return 0;
}
//-------------------------------------------------------------------------
//
//                          Initialization
//
//-------------------------------------------------------------------------
void FM_SP_SPACE_Init(void)
{
	FM_SP[DATATYPE_JW].FILE_MinLen = 512;					//set data len
	FM_SP[DATATYPE_JW].FILE_Type = DATATYPE_JW;
	FM_SP[DATATYPE_JW].curReadtSec = 0;
	FM_SP[DATATYPE_JW].W_R_status = FM_SP_WRITE_ENABLE;
	FM_SP[DATATYPE_JW].STARTSEC = SD_bpb.JwSecStartNo;//set start sector
	FM_SP[DATATYPE_JW].TOTALSEC = SD_JW_SEC_CNT;	//set total sector
	
	FM_SP[DATATYPE_ST8].FILE_MinLen = 512;
	FM_SP[DATATYPE_ST8].FILE_Type = DATATYPE_ST8;
	FM_SP[DATATYPE_ST8].curReadtSec = 0;
	FM_SP[DATATYPE_ST8].W_R_status = FM_SP_WRITE_ENABLE;
	FM_SP[DATATYPE_ST8].STARTSEC =	SD_bpb.StsSecStartNo;//SD_bpb.TestSecStartNo;
	FM_SP[DATATYPE_ST8].TOTALSEC = SD_STATUS_SEC_CNT;//SD_TEST_SEC_CNT;//TotalSecCnt
	
	FM_SP[DATATYPE_STS].FILE_MinLen = 512;
	FM_SP[DATATYPE_STS].FILE_Type = DATATYPE_STS;
	FM_SP[DATATYPE_STS].curReadtSec = 0;
	FM_SP[DATATYPE_STS].W_R_status = FM_SP_WRITE_ENABLE;
	FM_SP[DATATYPE_STS].STARTSEC = SD_bpb.StsSecStartNo;
	FM_SP[DATATYPE_STS].TOTALSEC = SD_STATUS_SEC_CNT;//TotalSecCnt
	
	FM_SP[DATATYPE_ANA].FILE_MinLen = 183*1024;
	FM_SP[DATATYPE_ANA].FILE_Type = DATATYPE_ANA;
	FM_SP[DATATYPE_ANA].curReadtSec = 0;
	FM_SP[DATATYPE_ANA].W_R_status = FM_SP_WRITE_ENABLE;
	FM_SP[DATATYPE_ANA].STARTSEC = SD_bpb.SigSecStartNo;
	FM_SP[DATATYPE_ANA].TOTALSEC = SD_bpb.MaxSigFileCnt*183*2;//TotalSecCnt
				
	FM_SP_POS.FILE_MinLen = 512;
	FM_SP_POS.FILE_Type = FM_TYPE_POS;
	FM_SP_POS.curReadtSec = 0;
	FM_SP_POS.W_R_status = FM_SP_WRITE_ENABLE;
	FM_SP_POS.STARTSEC = SD_bpb.PosSecStartNo;
	FM_SP_POS.TOTALSEC = SD_POS_SEC_CNT;
}
//sec: the start sec of posdata.
//num: total sector number of posdata.
//*fi: firest posindex of pos in "sec"
//*of: sector offset of the latest pos 
//*cnt: search action take to find the latest pos.
uint8_t FM_SP_FindLatestPos(uint8_t* fmBuf,uint32_t sec,uint32_t num,uint32_t* fi,uint32_t* of,uint32_t *cnt)
{
	uint32_t small,mid,big;
	POS_INFO *pos;
	uint8_t res;
	
	*cnt = 0;
	*of = 0;
	*fi = 0;
	
	if(num == 0)
		return 1;
	
	if(ReadSdSec(fmBuf,sec,512,1))
		return 2;
	
	pos = (POS_INFO*)fmBuf;
	if(FM_SP_PosCheckErr(pos,sec))
		return 3;
	*fi = pos->posIndex;

	small = 0;
	big = num - 1;
	mid = (big + small)/2;
	
	while(small != big)
	{
		if(*cnt > 500)
			return 6;
		(*cnt)++;
		
		res = 0;
		if(ReadSdSec(fmBuf,sec+mid,512,1))
			return 5;
		if(FM_SP_PosCheckErr(pos,sec+mid))
			res = 1;
		if((*fi)+mid != pos->posIndex)
			res = 1;
		if(res)
		{
			if(mid == big)
				break;
			big = mid;
			mid = (big + small)/2;
		}
		else
		{
			small = mid;
			mid = (big + small)/2;
		}
		if( (small+1) == big)
		{
			mid = big;
		}
	}
	*of = small;
	
	return 0;
}

//fine the latest pos, if no pos exit, init pos and write it into the first place.
uint8_t FM_SP_Pos_Init(uint8_t *fmBuf)
{
	uint8_t res = 0;
	uint32_t firstPosIndex,posOffset,cnt;
	
	res = FM_SP_FindLatestPos(	fmBuf,
								FM_SP_POS.STARTSEC,
								FM_SP_POS.TOTALSEC,
								&firstPosIndex,
								&posOffset,
								&cnt);
	
	//
	if(res)
	{
		FM_SP_SetPos(0,(uint8_t*)(&pos_Info));
		res = WriteSdSec((uint8_t*)(&pos_Info),pos_Info.PosSec,512,1);
	}
	else
	{
		res = ReadSdSec((uint8_t*)(&pos_Info),FM_SP_POS.STARTSEC+posOffset,512,1);
	}
	return res;
}
//
uint8_t FM_SP_Init(void)
{
	uint8_t res = 0;
	
	FM_SP_SPACE_Init();
	
	res = FM_SP_Pos_Init(FM_SP_Buf);
	return res;
}
//--------------------------------------------------------------------
//
//                                Read Action
//
//---------------------------------------------------------------------
uint32_t FM_SP_secLeft(uint32_t start,uint32_t total,uint32_t curRead,uint32_t nextWrite)
{
	if(curRead == nextWrite)
		return 0;
	
	if(curRead < nextWrite)
	{
		return (nextWrite-curRead);
	}
	if(curRead > nextWrite)
	{
		return (total-(curRead - nextWrite));
	}
	
	return 0;
}

void FM_SP_FindReadPtr(FILEMAN_SP_STRUCT *fm)
{
	//set fm-ReadtSec
	if(fm->curReadtSec==0)
	{
//		if(fm->FILE_Type == DATATYPE_STS)
//		{
//			fm->curReadtSec = FM_SP_SecAdd(pos_Info.PosData.NextSecToSave[fm->FILE_Type]
//										,fm->TOTALSEC-10240,
//										fm->STARTSEC,fm->TOTALSEC);
//		}
//		else
		{
		if(pos_Info.PosData.CopyInfoValid[fm->FILE_Type])
		{
			fm->curReadtSec = pos_Info.PosData.SecOfCopyStart[fm->FILE_Type];
		}
		else
		{
			fm->curReadtSec = FM_SP_SecAdd(pos_Info.PosData.NextSecToSave[fm->FILE_Type],1,
										fm->STARTSEC,fm->TOTALSEC);
		}
		}
		//
		
		fm->ReadSecTotal = FM_SP_secLeft(	fm->STARTSEC,
											fm->TOTALSEC,
											fm->curReadtSec,
											pos_Info.PosData.NextSecToSave[fm->FILE_Type]);
	}
	return;
}

//
void FM_SP_EnableReadAction(FILEMAN_SP_STRUCT *fm,uint32_t *tL, uint32_t *lL)
{
	//disable write 
	fm->W_R_status = FM_SP_READ_ENABLE;
	FM_SP_FindReadPtr(fm);
	*tL = fm->ReadSecTotal;
	*lL = FM_SP_secLeft(fm->STARTSEC,
						fm->TOTALSEC,
						fm->curReadtSec,
						pos_Info.PosData.NextSecToSave[fm->FILE_Type]);
	return;
}
//
void FM_SP_Setname(uint8_t *buf,const char name[],uint8_t maxlen)
{
	uint8_t i;
	
	for(i=0;i<maxlen;i++)
	{
		buf[i] = '\0';
	}
	for(i=0;i<maxlen;i++)
	{
		buf[i] = name[i];
		if(name[i] == '\0')
			break;
	}
	if(i == maxlen)
		buf[maxlen-1] = '\0';
	
	return;
}


/*
 * @brief  
 */
uint32_t TenMul(uint8_t times)
{
	uint32_t rtl=1;
	while(times)
	{
		rtl *= 10;
		times--;
	}
	return rtl;
}
//
void ValToStr(uint8_t *buf,uint32_t val,uint8_t len,uint8_t maxlen)
{
	uint8_t i;
	for(i=0;i<maxlen;i++)
		buf[i] = '\0';
	if(len>=maxlen)
		return;
	for(i=0;i<len;i++)
	{
		buf[i] = (val%TenMul(len-i)) / TenMul(len-i-1) + 0x30;
	}
	return;
}
void TimeToStr(uint8_t *buf,uint8_t ver,uint8_t *timeptr,uint8_t maxlen)
{
	uint8_t tmp[6],i,len=0;
	
	#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
		OS_CPU_SR  cpu_sr = 0u;
	#endif

	OS_ENTER_CRITICAL();
	for(i=0;i<6;i++)
	{
		tmp[i] = *timeptr;
		timeptr++;
	}
	OS_EXIT_CRITICAL();
	
	for(i=0;i<maxlen;i++)
		buf[i] = '\0';
	
	buf[len++] = 0x32;
	buf[len++] = 0x30;
	buf[len++] = 0x30 + ((tmp[0] /10)%10);
	buf[len++] = 0x30 + ((tmp[0] /1 )%10);
	if(ver)
		buf[len++] = '-';
	buf[len++] = 0x30 + ((tmp[1] /10)%10);
	buf[len++] = 0x30 + ((tmp[1] /1 )%10);
	if(ver)
		buf[len++] = '-';
	buf[len++] = 0x30 + ((tmp[2] /10)%10);
	buf[len++] = 0x30 + ((tmp[2] /1 )%10);
	
	if(ver)
		buf[len++] = ' ';
	
	buf[len++] = 0x30 + ((tmp[3] /10)%10);
	buf[len++] = 0x30 + ((tmp[3] /1 )%10);
	if(ver)
		buf[len++] = '!';
	buf[len++] = 0x30 + ((tmp[4] /10)%10);
	buf[len++] = 0x30 + ((tmp[4] /1 )%10);
	if(ver)
		buf[len++] = '!';
	buf[len++] = 0x30 + ((tmp[5] /10)%10);
	buf[len++] = 0x30 + ((tmp[5] /1 )%10);
	return;
}
//
uint8_t FM_SP_testfun(uint8_t *buf)
{
	return 0;
}

#define SET32b(buf,val)	(*((uint8_t*)(buf)))=(uint8_t)((val)>>0); \
						(*(((uint8_t*)(buf))+1))=(uint8_t)((val)>>8); \
						(*(((uint8_t*)(buf))+2))=(uint8_t)((val)>>16); \
						(*(((uint8_t*)(buf))+3))=(uint8_t)((val)>>24);
//Read file information of all kind.
uint8_t FM_SP_ReadFileInf(uint8_t *buf, 
							uint32_t *lenRead,
							uint32_t toRead,
							uint8_t *timeptr,
							uint16_t ID,
							uint8_t* sum)
{
	uint8_t len=0,i,ver=0;
	uint32_t totallen = 0,lenleft,STSlen,ST8len,ANAlen,POWlen;
	const uint8_t FILESTART = 7;
	
	*lenRead = 0;
	if(toRead<512)
		return 1;
	if(	FM_SP[DATATYPE_STS].W_R_status== FM_SP_READ_ENABLE||
		FM_SP[DATATYPE_ST8].W_R_status== FM_SP_READ_ENABLE||
		FM_SP[DATATYPE_ANA].W_R_status== FM_SP_READ_ENABLE||
		FM_SP[DATATYPE_JW].W_R_status== FM_SP_READ_ENABLE)
		return 2;
	
	FM_SP_EnableReadAction(	&(FM_SP[DATATYPE_STS]),&STSlen,&lenleft);
	FM_SP_EnableReadAction(	&(FM_SP[DATATYPE_ST8]),&ST8len,&lenleft);
	FM_SP_EnableReadAction(	&(FM_SP[DATATYPE_ANA]),&ANAlen,&lenleft);
	FM_SP_EnableReadAction(	&(FM_SP[DATATYPE_JW]),&POWlen,&lenleft);
	totallen += (STSlen*512);
	totallen += (ST8len*512);
	totallen += (ANAlen*512);
	totallen += (POWlen*512);
	totallen += 200;//head
	totallen += 1;//ECC_SUM
	
	if(STSlen==0&&ST8len!=0)
		ver = 1;
	
	buf[len] = 0x55;////////////////////////////////////////////1
	len +=1;
	buf[len] = 0xAA;////////////////////////////////////////////1
	len +=1;
	SET32b(buf+len,totallen);///////////////////////////////////4
	len +=4;
	buf[len] = 0;///////////////////////////////////////////////1
	len +=1;
	
	SET32b(buf+len,0x1A9B5674);/////////////////////////////////4
	len +=4;
	buf[len] = 1;///////////////////////////////////////////////1
	len +=1;
	buf[len] = 4;///////////////////////////////////////////////1
	len +=1;
	SET32b(buf+len,totallen);///////////////////////////////////4
	len +=4;
	
	
	ValToStr(buf+len,ID,8,10);/////////////////////////////////32
	len+=10;
	TimeToStr(buf+len,ver,timeptr,32);/////////////////////////32
	len+=32;
	
	SET32b(buf+len,STSlen*512);/////////////////////////////////4
	len +=4;
	FM_SP_Setname(buf+len,"STS",32);///////////////////////////32
	len +=32;
	SET32b(buf+len,ST8len*512);/////////////////////////////////4
	len +=4;
	FM_SP_Setname(buf+len,"STS",32);///////////////////////////32
	len +=32;
	SET32b(buf+len,ANAlen*512);/////////////////////////////////4
	len +=4;
	FM_SP_Setname(buf+len,"ANA",32);///////////////////////////32
	len +=32;
	SET32b(buf+len,POWlen*512);/////////////////////////////////4
	len +=4;
	FM_SP_Setname(buf+len,"POW",32);///////////////////////////32
	len +=32;
	
	SET32b(buf+len,0XB66BA55A);/////////////////////////////////4
	len +=4;
	
	for(i=FILESTART;i<len;i++)
	{
		*sum += buf[i];
	}
	
	*lenRead = len;
	return 0;
}
//
uint8_t FM_SP_FinishRead(void)
{
	uint8_t res = 0;
	
	if( FM_SP[DATATYPE_JW].W_R_status ==FM_SP_WRITE_ENABLE||
		FM_SP[DATATYPE_JW].W_R_status ==FM_SP_WRITE_ENABLE||
		FM_SP[DATATYPE_JW].W_R_status ==FM_SP_WRITE_ENABLE||
		FM_SP[DATATYPE_JW].W_R_status ==FM_SP_WRITE_ENABLE
	)
		return 1;
	
	pos_Info.PosData.CopyInfoValid[DATATYPE_JW] = 1;
	pos_Info.PosData.SecOfCopyStart[DATATYPE_JW] = FM_SP[DATATYPE_JW].curReadtSec;
	pos_Info.PosData.TotSavedSecCnt[DATATYPE_JW] = 0;
	FM_SP[DATATYPE_JW].curReadtSec = 0;
	FM_SP[DATATYPE_JW].W_R_status =FM_SP_WRITE_ENABLE;
	
	pos_Info.PosData.CopyInfoValid[DATATYPE_ST8] = 1;
	pos_Info.PosData.SecOfCopyStart[DATATYPE_ST8] = FM_SP[DATATYPE_ST8].curReadtSec;
	pos_Info.PosData.TotSavedSecCnt[DATATYPE_ST8] = 0;
	FM_SP[DATATYPE_ST8].curReadtSec = 0;
	FM_SP[DATATYPE_ST8].W_R_status =FM_SP_WRITE_ENABLE;
	
	pos_Info.PosData.CopyInfoValid[DATATYPE_STS] = 1;
	pos_Info.PosData.SecOfCopyStart[DATATYPE_STS] = FM_SP[DATATYPE_STS].curReadtSec;
	pos_Info.PosData.TotSavedSecCnt[DATATYPE_STS] = 0;
	FM_SP[DATATYPE_STS].curReadtSec = 0;
	FM_SP[DATATYPE_STS].W_R_status =FM_SP_WRITE_ENABLE;
	
	pos_Info.PosData.CopyInfoValid[DATATYPE_ANA] = 1;
	pos_Info.PosData.SecOfCopyStart[DATATYPE_ANA] = FM_SP[DATATYPE_ANA].curReadtSec;
	pos_Info.PosData.TotSavedSecCnt[DATATYPE_ANA] = 0;
	FM_SP[DATATYPE_ANA].curReadtSec = 0;
	FM_SP[DATATYPE_ANA].W_R_status =FM_SP_WRITE_ENABLE;
	
	//renew pos_Info
	FM_SP_NewPos(&pos_Info,1);
	res = WriteSdSec((uint8_t*)&(pos_Info.ID),pos_Info.PosSec,512,1);
	
	return res;
}
uint8_t SD_READBUF[1024*20];
//when return != 0, ignore para len
uint8_t FM_SP_ReadFile(FILEMAN_SP_STRUCT *fm,uint8_t *buf, uint32_t *len,uint32_t toRead,uint8_t* sum)
{
	uint8_t res = 0;
	uint32_t i,sec,secleft;

	*len = 0;	//reset len
	
	//set fm-ReadtSec
	FM_SP_FindReadPtr(fm);
	
	if(fm->curReadtSec == 0xffffffff)
	{
//		fm->W_R_status =FM_SP_WRITE_ENABLE;
//		fm->ReadtSec = 0;
		return 0xfe;
	}
	//fm->ReadtSec check
	if(fm->curReadtSec == pos_Info.PosData.NextSecToSave[fm->FILE_Type])
	{
//		fm->ReadtSec = 0;
//		fm->W_R_status =FM_SP_WRITE_ENABLE;
		return 0xff;
	}
	
	while((*len)<toRead)
	{
		sec = (toRead - (*len))/512;
		if(fm->curReadtSec>pos_Info.PosData.NextSecToSave[fm->FILE_Type])
			secleft = fm->STARTSEC+fm->TOTALSEC-fm->curReadtSec;
		else
			secleft = pos_Info.PosData.NextSecToSave[fm->FILE_Type]-fm->curReadtSec;
		if(sec>secleft)
			sec = secleft;
		if(sec>40)
			sec = 40;
		
		if(fm->FILE_MinLen>=512&&fm->FILE_MinLen%512==0&&sec>0)
		{
			res = ReadSdSec(SD_READBUF,fm->curReadtSec,512,sec);
			if(res)
				break;
			
			for(i=0;i<512*sec;i++)
			{
				buf[i] = SD_READBUF[i];
				*sum += buf[i];
			}
			buf+=(sec*512);
			(*len) += (sec*512);
			
		}
		else
		{
			sec = 1;
			res = ReadSdSec(FM_SP_Buf,fm->curReadtSec,512,sec);		
			if(res)
				break;
			
			for(i=0;i<512&&i<fm->FILE_MinLen&&toRead>0;i++)
			{
				*buf = FM_SP_Buf[i];
				*sum += FM_SP_Buf[i];
				buf++;
				(*len)++;
			}
		}
		
		fm->curReadtSec = FM_SP_SecAdd(fm->curReadtSec,sec,fm->STARTSEC,fm->TOTALSEC);
		if(fm->curReadtSec == pos_Info.PosData.NextSecToSave[fm->FILE_Type])
		{
//			pos_Info.PosData.CopyInfoValid[fm->dataType] = 1;
//			pos_Info.PosData.SecOfCopyStart[fm->dataType] =fm->ReadtSec;
//			pos_Info.PosData.TotSavedSecCnt[fm->dataType] = 0;
//			
//			//renew pos_Info
//			FM_SP_NewPos(&pos_Info,1);
//			
//			res = WriteSdSec((uint8_t*)&(pos_Info.ID),pos_Info.PosSec,512,1);
//			fm->ReadtSec = 0xffffffff;
			break;
		}
		
	}
	return res;
}

//-------------------------------------------------------------------------
//
//                           Write Action
//
//-------------------------------------------------------------------------
uint8_t FM_SP_renewPos(FILEMAN_SP_STRUCT *fm,POS_INFO *info,uint32_t cnt)
{
	uint8_t type;
	
	// len and sector cnt check
	if(((fm->FILE_MinLen+511)/512)!=cnt)
		return 0xA1;
	
	//renew pos_info
	type = fm->FILE_Type;
	info->PosData.NextSecToSave[type] = FM_SP_SecAdd(info->PosData.NextSecToSave[type],
													cnt,
													fm->STARTSEC,
													fm->TOTALSEC);
	
	info->PosData.TotSavedSecCnt[type] += cnt;
	if(info->PosData.TotSavedSecCnt[type]>=fm->TOTALSEC)
	{
		info->PosData.CopyInfoValid[type]=0;
	}
	//renew info
	FM_SP_NewPos(info,1);
	return 0;
}

//Save buf[]
uint8_t FM_SP_SaveDataToFile(FILEMAN_SP_STRUCT *fm,
							uint8_t *buf, 
							uint32_t len,
							uint32_t *bytesWritten)
{
	uint8_t res = 0;
	uint16_t i;
	uint32_t cnt=0,sec;
	
	*bytesWritten = 0;
	
	if(fm->W_R_status != FM_SP_WRITE_ENABLE)
		return 0xA0;
	
	//len check;
	if(len != fm->FILE_MinLen)
		return 0xff;
	
	sec = pos_Info.PosData.NextSecToSave[fm->FILE_Type];
	
	while(len>0&&(!res))
	{
		for(i=0;i<512&&len>0;i++)
		{
			FM_SP_Buf[i] = *buf;
			buf++;
			(*bytesWritten)++;
			len--;
		}
		//save data
		res = WriteSdSec(FM_SP_Buf,sec,512,1);
		sec = FM_SP_SecAdd(sec,1,fm->STARTSEC,fm->TOTALSEC);
		cnt++;
	}
	if(!res)
	{
		res = FM_SP_renewPos(fm,&pos_Info,cnt);
		//renew position
		if(!res)
		{
			//save ptr 
			res = WriteSdSec((uint8_t*)(&pos_Info),pos_Info.PosSec,512,1);
		}
	}

	return res;
}





//EOF
